package com.sun.syndication.feed.module.wcm.io;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jdom.Element;
import org.jdom.Namespace;

import com.sun.syndication.feed.module.Module;
import com.sun.syndication.feed.module.wcm.WCMModule;
import com.sun.syndication.feed.module.wcm.WCMModuleImpl;
import com.sun.syndication.feed.module.wcm.types.Component;
import com.sun.syndication.feed.module.wcm.types.Path;
import com.sun.syndication.feed.module.wcm.types.TemplateMap;
import com.sun.syndication.io.ModuleParser;
import com.sun.syndication.io.impl.DateParser;

/**
 * 
 * <p>This file is extracted from Websphere Portal 6.1 FeedServiceWCPPlugin.jar
 * 
 * <p>Original class is <code>com.ibm.workplace.feed.plugin.wcm.module.WCMModuleParser</code>
 *
 */
public class WCMModuleParser implements ModuleParser {

	public WCMModuleParser() {
	}

	public String getNamespaceUri() {
		return "http://purl.org/net/ibmfeedsvc/wcm/1.0";
	}

	public Module parse(Element pRoot) {
		boolean foundWCMElements = false;
		WCMModule lvWcmModule = new WCMModuleImpl();
		String lvTitle = "entry";
		Element lvTitleElement = pRoot.getChild("title");
		if (lvTitleElement != null)
			lvTitle = lvTitleElement.getTextTrim();
		if (logger.isLoggable(Level.FINEST))
			logger.log(Level.FINEST, "parse: Begin parsing feed entry: "
					+ lvTitle);
		Element lvElement = pRoot.getChild("action", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setAction(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("itemType", WCM_NS) == null ? pRoot.getChild(
				"objectType", WCM_NS) : pRoot.getChild("itemType", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setObjectType(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("authoringTemplate", WCM_NS) == null ? pRoot
				.getChild("contentType", WCM_NS) : pRoot.getChild(
				"authoringTemplate", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setContentType(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("library", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setLibrary(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("displayTitle", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setDisplayTitle(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("defaultContent", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setDefaultContent(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("keywords", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setKeywords(lvElement.getTextTrim());
		}
		lvElement = pRoot.getChild("publishDate", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setPublicationDate(DateParser.parseDate(lvElement.getTextTrim()));
		}
		lvElement = pRoot.getChild("expirationDate", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setExpirationDate(DateParser.parseDate(lvElement.getTextTrim()));
		}
		lvElement = pRoot.getChild("genDateOne", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setGenDateOne(DateParser.parseDate(lvElement.getTextTrim()));
		}
		lvElement = pRoot.getChild("genDateTwo", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setGenDateTwo(DateParser.parseDate(lvElement.getTextTrim()));
		}
		List lvElementList = pRoot.getChildren("author", WCM_NS);
		if (lvElementList.size() > 0) {
			foundWCMElements = true;
			lvWcmModule.setAuthors(parseMulti(lvElementList));
		}
		lvElementList = pRoot.getChildren("owner", WCM_NS);
		if (lvElementList.size() > 0) {
			foundWCMElements = true;
			lvWcmModule.setOwners(parseMulti(lvElementList));
		}
		lvElementList = pRoot.getChildren("path", WCM_NS).size() <= 0 ? pRoot
				.getChildren("location", WCM_NS) : pRoot.getChildren("path",
				WCM_NS);
		if (lvElementList.size() > 0) {
			foundWCMElements = true;
			lvWcmModule = addLocations(lvWcmModule, lvElementList);
		}
		lvElementList = pRoot.getChildren("additionalViewer", WCM_NS).size() <= 0 ? pRoot
				.getChildren("addlViewer", WCM_NS)
				: pRoot.getChildren("additionalViewer", WCM_NS);
		if (lvElementList.size() > 0) {
			foundWCMElements = true;
			lvWcmModule.setAddlViewers(parseMulti(lvElementList));
		}
		lvElement = pRoot.getChild("createLinks", WCM_NS) == null ? pRoot.getChild(
				"parents", WCM_NS) : pRoot.getChild("createLinks", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvElementList = lvElement.getChildren("parentGuid", WCM_NS);
			if (lvElementList.size() > 0)
				lvWcmModule.setParents(parseMulti(lvElementList));
		}
		lvElement = pRoot.getChild("children", WCM_NS);
		if (lvElement != null) {
			foundWCMElements = true;
			lvWcmModule.setChildrenAction(lvElement.getAttributeValue("action"));
			lvWcmModule.setChildrenPosition(lvElement.getAttributeValue("position"));
			lvElementList = lvElement.getChildren("childGuid", WCM_NS);
			if (lvElementList.size() > 0)
				lvWcmModule.setChildren(parseMulti(lvElementList));
		}
		lvElementList = pRoot.getChildren("access", WCM_NS).size() <= 0 ? pRoot
				.getChildren("entitlement", WCM_NS) : pRoot.getChildren(
				"access", WCM_NS);
		if (lvElementList.size() > 0)
			lvWcmModule = setEntitlements(lvWcmModule, lvElementList);
		lvElement = pRoot.getChild("workflow", WCM_NS);
		if (lvElement != null)
			lvWcmModule = setWorkflow(lvWcmModule, lvElement);
		lvElementList = pRoot.getChildren("element", WCM_NS).size() <= 0 ? pRoot
				.getChildren("component", WCM_NS) : pRoot.getChildren(
				"element", WCM_NS);
		if (lvElementList.size() > 0)
			lvWcmModule = addComponents(lvWcmModule, lvElementList);
		lvElementList = pRoot.getChildren("templateMap", WCM_NS).size() <= 0 ? pRoot
				.getChildren("tmpltMap", WCM_NS) : pRoot.getChildren(
				"templateMap", WCM_NS);
		if (lvElementList.size() > 0)
			lvWcmModule = addTmpltMaps(lvWcmModule, lvElementList);
		if (logger.isLoggable(Level.FINEST))
			logger.log(Level.FINEST, "parse: End parsing feed entry: "
					+ lvTitle);
		return foundWCMElements ? lvWcmModule : null;
	}

	private List parseMulti(List pElements) {
		List lvValues = new ArrayList();
		for (int i = 0; i < pElements.size(); i++) {
			Element lvElement = (Element) pElements.get(i);
			lvValues.add(lvElement.getTextTrim());
		}

		return lvValues;
	}

	private WCMModule setEntitlements(WCMModule pCurrentModule, List pElements) {
		List lvUser = new ArrayList();
		List lvContributor = new ArrayList();
		List lvEditor = new ArrayList();
		List lvManager = new ArrayList();
		for (int i = 0; i < pElements.size(); i++) {
			Element lvElement = (Element) pElements.get(i);
			String lvType = lvElement.getAttributeValue("type");
			if (lvType == null) {
				lvUser.add(lvElement.getTextTrim());
				continue;
			}
			if (lvType.equalsIgnoreCase("user") || lvType.equalsIgnoreCase("live")) {
				lvUser.add(lvElement.getTextTrim());
				continue;
			}
			if (lvType.equalsIgnoreCase("contributor")
					|| lvType.equalsIgnoreCase("read")) {
				lvContributor.add(lvElement.getTextTrim());
				continue;
			}
			if (lvType.equalsIgnoreCase("editor")
					|| lvType.equalsIgnoreCase("edit")) {
				lvEditor.add(lvElement.getTextTrim());
				continue;
			}
			if (lvType.equalsIgnoreCase("manager")
					|| lvType.equalsIgnoreCase("delete")) {
				lvManager.add(lvElement.getTextTrim());
				continue;
			}
			if (logger.isLoggable(Level.FINEST))
				logger.log(Level.FINEST,
						"setEntitlements: Invalid value specified for Entitlement type attribute: "
								+ lvType
								+ " Entitlement element will be ignored.");
		}

		pCurrentModule.setUserEntitlements(lvUser);
		pCurrentModule.setContributorEntitlements(lvContributor);
		pCurrentModule.setEditorEntitlements(lvEditor);
		pCurrentModule.setManagerEntitlements(lvManager);
		return pCurrentModule;
	}

	private WCMModule setWorkflow(WCMModule pWcmModule, Element pWkflowRoot) {
		String lvWorkflow = "";
		String lvWkflowStage = "";
		lvWorkflow = pWkflowRoot.getAttributeValue("name");
		lvWkflowStage = pWkflowRoot.getChildTextTrim("workflowStage", WCM_NS);
		if (logger.isLoggable(Level.FINEST))
			logger.log(Level.FINEST,
					"setWorkflow: Setting WCMModule's workflow: " + lvWorkflow
							+ " and stage: " + lvWkflowStage);
		pWcmModule.setWorkflow(lvWorkflow);
		pWcmModule.setWorkflowStage(lvWkflowStage);
		return pWcmModule;
	}

	private WCMModule addComponents(WCMModule pWcmModule, List pElements) {
		for (int i = 0; i < pElements.size(); i++) {
			Element lvElement = (Element) pElements.get(i);
			String lvName = lvElement.getAttributeValue("name");
			String lvType = lvElement.getChildTextTrim("type", WCM_NS);
			if (pWcmModule.getObjectType().equalsIgnoreCase("component"))
				if (lvType.equalsIgnoreCase("text")
						|| lvType.equalsIgnoreCase("SharedText"))
					pWcmModule.setObjectType("SharedText");
				else if (lvType.equalsIgnoreCase("rich text")
						|| lvType.equalsIgnoreCase("SharedRichText"))
					pWcmModule.setObjectType("SharedRichText");
				else if (lvType.equalsIgnoreCase("shortText")
						|| lvType.equalsIgnoreCase("SharedShortText"))
					pWcmModule.setObjectType("SharedShortText");
				else if (lvType.equalsIgnoreCase("file")
						|| lvType.equalsIgnoreCase("SharedFile"))
					pWcmModule.setObjectType("SharedFile");
				else if (lvType.equalsIgnoreCase("html")
						|| lvType.equalsIgnoreCase("SharedHTML"))
					pWcmModule.setObjectType("SharedHTML");
				else if (lvType.equalsIgnoreCase("image")
						|| lvType.equalsIgnoreCase("SharedImage"))
					pWcmModule.setObjectType("SharedImage");
				else if (lvType.equalsIgnoreCase("date")
						|| lvType.equalsIgnoreCase("SharedDate"))
					pWcmModule.setObjectType("SharedDate");
				else if (lvType.equalsIgnoreCase("link")
						|| lvType.equalsIgnoreCase("SharedLink"))
					pWcmModule.setObjectType("SharedLink");
				else if (lvType.equalsIgnoreCase("number")
						|| lvType.equalsIgnoreCase("SharedNumber"))
					pWcmModule.setObjectType("SharedNumber");
				else if (lvType.equalsIgnoreCase("userSelect")
						|| lvType.equalsIgnoreCase("SharedUserSelect"))
					pWcmModule.setObjectType("SharedUserSelect");
				else if (lvType.equalsIgnoreCase("styleSheet")
						|| lvType.equalsIgnoreCase("SharedStyleSheet"))
					pWcmModule.setObjectType("SharedStyleSheet");
			boolean flag = ("html".equalsIgnoreCase(lvType)
					|| "image".equalsIgnoreCase(lvType)
					|| "file".equalsIgnoreCase(lvType) || "styleSheet"
					.equalsIgnoreCase(lvType))
					&& lvElement.getChild("source", WCM_NS) != null;
			Element lvValueElement = flag ? lvElement.getChild("source", WCM_NS) : lvElement
					.getChild("value", WCM_NS);
			if ("html".equalsIgnoreCase(lvType)
					&& lvElement.getChild("source", WCM_NS) != null
					&& lvElement.getChild("value", WCM_NS) == null)
				lvType = "htmlfile";
			else if ("html".equalsIgnoreCase(lvType)
					&& lvElement.getChild("source", WCM_NS) != null
					&& lvElement.getChild("value", WCM_NS) != null)
				lvValueElement = lvElement.getChild("value", WCM_NS);
			String lvValue = lvValueElement.getTextTrim();
			if (logger.isLoggable(Level.FINEST))
				logger.log(Level.FINEST,
						"addComponents: Parsing component element with name: "
								+ lvName + " and type: " + lvType);
			Component lvContentComponent = null;
			lvContentComponent = new Component(lvName, lvType, lvValue);
			lvContentComponent.setFormat(lvElement.getChildTextTrim("format", WCM_NS));
			lvContentComponent.setAltText(lvElement.getChildTextTrim("altText", WCM_NS));
			lvContentComponent.setBorder(lvElement.getChildTextTrim("border", WCM_NS));
			lvContentComponent.setHeight(lvElement.getChildTextTrim("height", WCM_NS));
			lvContentComponent.setWidth(lvElement.getChildTextTrim("width", WCM_NS));
			lvContentComponent
					.setHtmlName(lvElement.getChildTextTrim("htmlName", WCM_NS));
			lvContentComponent.setMediaType(lvElement.getChildTextTrim("mediaType",
					WCM_NS));
			lvContentComponent
					.setCssTitle(lvElement.getChildTextTrim("cssTitle", WCM_NS));
			Element lvLinkText = lvElement.getChild("linkText", WCM_NS);
			if (lvLinkText != null) {
				lvContentComponent.setLinkTextLibrary(lvLinkText
						.getAttributeValue("library"));
				lvContentComponent.setLinkTextType(lvLinkText
						.getAttributeValue("type"));
				lvContentComponent.setLinkText(lvLinkText.getTextTrim());
			}
			lvContentComponent.setValueObjectType(lvValueElement
					.getAttributeValue("itemType") == null ? lvValueElement
					.getAttributeValue("objectType") : lvValueElement
					.getAttributeValue("itemType"));
			lvContentComponent.setValueType(lvValueElement
					.getAttributeValue("type"));
			lvContentComponent.setValueReferenceLibrary(lvValueElement
					.getAttributeValue("library"));
			lvContentComponent.setAddlAttributes(lvElement.getChildTextTrim(
					"additionalAttributes", WCM_NS) == null ? lvElement
					.getChildTextTrim("addlAttributes", WCM_NS) : lvElement
					.getChildTextTrim("additionalAttributes", WCM_NS));
			lvContentComponent.setLinkDesc(lvElement.getChildTextTrim("linkDescription",
					WCM_NS) == null ? lvElement.getChildTextTrim("linkDesc", WCM_NS)
					: lvElement.getChildTextTrim("linkDescription", WCM_NS));
			lvContentComponent.setLinkTarget(lvElement.getChildTextTrim("linkTarget",
					WCM_NS));
			lvContentComponent.setQueryString(lvElement.getChildTextTrim("queryString",
					WCM_NS));
			String lvAllowClear = lvElement.getChildTextTrim("allowClear", WCM_NS);
			if (lvAllowClear != null && lvAllowClear.equalsIgnoreCase("false"))
				lvContentComponent.setAllowClear(false);
			lvContentComponent.setPDMLibrary(lvElement.getChildTextTrim("pdmLibrary"));
			String lockVer = lvElement.getChildTextTrim("lockToVersion", WCM_NS);
			if (lockVer != null && lockVer.equalsIgnoreCase("true"))
				lvContentComponent.setLockToVersion();
			if (lvType.equalsIgnoreCase("File") || lvType.equalsIgnoreCase("Image")
					|| lvType.equalsIgnoreCase("styleSheet")) {
				String lvFileName = lvElement.getChildTextTrim("fileName", WCM_NS);
				if ((lvFileName == null || lvFileName.equals("")) && lvValue != null)
					lvFileName = lvValue.substring(lvValue.lastIndexOf("/") + 1);
				if (logger.isLoggable(Level.FINEST))
					logger.log(Level.FINEST, "addComponents: File name: "
							+ lvFileName);
				lvContentComponent.setFileName(lvFileName);
			}
			if (lvContentComponent == null)
				continue;
			pWcmModule.set(lvName, lvContentComponent);
			if (logger.isLoggable(Level.FINEST))
				logger.log(Level.FINEST,
						"addComponents: Created Component object: " + lvName);
		}

		return pWcmModule;
	}

	private WCMModule addTmpltMaps(WCMModule pWcmModule, List pElements) {
		List lvMaps = new ArrayList();
		for (int i = 0; i < pElements.size(); i++) {
			Element lvElement = (Element) pElements.get(i);
			String lvAuth = lvElement.getAttributeValue("authoring");
			String lvPresentation = lvElement.getAttributeValue("presentation");
			if (logger.isLoggable(Level.FINEST))
				logger.log(Level.FINEST,
						"addTmpltMaps: Creating template mapping of Authoring Tmplt: "
								+ lvAuth + " to Presentation Tmplt: " + lvPresentation);
			TemplateMap tMap = new TemplateMap(lvAuth, lvPresentation);
			lvMaps.add(tMap);
		}

		pWcmModule.setTmpltMaps(lvMaps);
		return pWcmModule;
	}

	private WCMModule addLocations(WCMModule pWcmModule, List pElements) {
		List lvLocations = new ArrayList();
		for (int i = 0; i < pElements.size(); i++) {
			Element lvElement = (Element) pElements.get(i);
			String lvLibrary = lvElement.getAttributeValue("library");
			String lvPath = lvElement.getTextTrim();
			if (logger.isLoggable(Level.FINEST))
				logger.log(Level.FINEST,
						"addLocations: Created Path object with path: " + lvPath
								+ " and library: "
								+ (lvLibrary != null ? lvLibrary : "-Default-"));
			Path lvLoc = new Path(lvLibrary, lvPath);
			lvLocations.add(lvLoc);
		}

		pWcmModule.setLocations(lvLocations);
		return pWcmModule;
	}

	private static final Namespace WCM_NS = Namespace
			.getNamespace("http://purl.org/net/ibmfeedsvc/wcm/1.0");
	private static Logger logger;

}
